{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "b45f4b54-fc3f-4456-8529-7e280ac48f35",
   "metadata": {},
   "source": [
    "Chapter 01\n",
    "\n",
    "# 向量正交分解\n",
    "《线性代数》 | 鸢尾花书：数学不难"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4565462e-7d5a-4340-ac66-a7321429dd98",
   "metadata": {},
   "source": [
    "这段代码的数学核心思想是：**将一个二维向量 $\\mathbf{a}$ 沿任意旋转角 $\\theta$ 所定义的正交基向量进行正交分解（orthogonal decomposition）**，即把 $\\mathbf{a}$ 拆分成在这组正交基下的两个分量，并验证它们之和仍等于原始向量。\n",
    "\n",
    "---\n",
    "\n",
    "### 数学背景和目标\n",
    "\n",
    "已知一个二维向量 $\\mathbf{a} = \\begin{bmatrix} 3 \\\\ 4 \\end{bmatrix}$，我们希望将它分解为两个正交方向上的分量：\n",
    "\n",
    "- 方向一：与单位向量 $\\mathbf{v}_1$ 方向相同，定义为  \n",
    "  $$\\mathbf{v}_1 = \\begin{bmatrix} \\cos\\theta \\\\ \\sin\\theta \\end{bmatrix}$$\n",
    "- 方向二：与单位向量 $\\mathbf{v}_2$ 方向相同，垂直于 $\\mathbf{v}_1$，定义为  \n",
    "  $$\\mathbf{v}_2 = \\begin{bmatrix} -\\sin\\theta \\\\ \\cos\\theta \\end{bmatrix}$$\n",
    "\n",
    "$\\mathbf{v}_1$ 和 $\\mathbf{v}_2$ 构成一个二维空间中的**标准正交基底（orthonormal basis）**。\n",
    "\n",
    "我们要做的是将 $\\mathbf{a}$ 写成两个正交向量的和，即：\n",
    "$$\n",
    "\\mathbf{a} = \\mathbf{a}_{\\mathbf{v}_1} + \\mathbf{a}_{\\mathbf{v}_2}\n",
    "$$\n",
    "其中：\n",
    "\n",
    "- $\\mathbf{a}_{\\mathbf{v}_1}$ 是 $\\mathbf{a}$ 在 $\\mathbf{v}_1$ 方向上的投影；\n",
    "- $\\mathbf{a}_{\\mathbf{v}_2}$ 是 $\\mathbf{a}$ 在 $\\mathbf{v}_2$ 方向上的投影。\n",
    "\n",
    "---\n",
    "\n",
    "### 投影计算方法\n",
    "\n",
    "对于任意向量 $\\mathbf{a}$ 和单位向量 $\\mathbf{v}$，其在 $\\mathbf{v}$ 方向上的投影公式为：\n",
    "\n",
    "- **标量投影（投影坐标）：**  \n",
    "  $$\n",
    "  \\text{scalar\\_proj}_{\\mathbf{v}}(\\mathbf{a}) = \\mathbf{a} \\cdot \\mathbf{v}\n",
    "  $$\n",
    "- **向量投影：**  \n",
    "  $$\n",
    "  \\text{proj}_{\\mathbf{v}}(\\mathbf{a}) = (\\mathbf{a} \\cdot \\mathbf{v}) \\cdot \\mathbf{v}\n",
    "  $$\n",
    "\n",
    "因此我们得到两个向量投影：\n",
    "\n",
    "$$\n",
    "\\mathbf{a}_{\\mathbf{v}_1} = (\\mathbf{a} \\cdot \\mathbf{v}_1) \\cdot \\mathbf{v}_1 \\\\\n",
    "\\mathbf{a}_{\\mathbf{v}_2} = (\\mathbf{a} \\cdot \\mathbf{v}_2) \\cdot \\mathbf{v}_2\n",
    "$$\n",
    "\n",
    "最终验证：\n",
    "$$\n",
    "\\mathbf{a}_{\\mathbf{v}_1} + \\mathbf{a}_{\\mathbf{v}_2} = \\mathbf{a}\n",
    "$$\n",
    "\n",
    "---\n",
    "\n",
    "### 数值代入说明\n",
    "\n",
    "代码中 $\\theta = 30^\\circ$，被转化为弧度：\n",
    "$$\n",
    "\\theta = \\frac{30}{180} \\pi = \\frac{\\pi}{6}\n",
    "$$\n",
    "\n",
    "代入后单位向量变为：\n",
    "$$\n",
    "\\mathbf{v}_1 = \\begin{bmatrix} \\cos\\left(\\frac{\\pi}{6}\\right) \\\\ \\sin\\left(\\frac{\\pi}{6}\\right) \\end{bmatrix}\n",
    "= \\begin{bmatrix} \\frac{\\sqrt{3}}{2} \\\\ \\frac{1}{2} \\end{bmatrix}, \\quad\n",
    "\\mathbf{v}_2 = \\begin{bmatrix} -\\frac{1}{2} \\\\ \\frac{\\sqrt{3}}{2} \\end{bmatrix}\n",
    "$$\n",
    "\n",
    "然后进行点积、缩放、拼接，得到两个投影向量，其和正好等于原始向量 $\\mathbf{a}$，即完成一次**二维向量在任意正交基下的分解**。\n",
    "\n",
    "---\n",
    "\n",
    "这段代码在数学上等价于对 $\\mathbb{R}^2$ 中任意向量做一次基变换和投影运算，是线性代数中“正交投影”与“坐标变换”的经典操作。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c672e08b-6d94-4d7d-a411-74f9a13dd985",
   "metadata": {},
   "source": [
    "## 初始化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "89cfcc17-cf11-4abb-bdb3-d92092b59a32",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "038bf613-e8d9-40f5-a5ca-c01c86c6e567",
   "metadata": {},
   "source": [
    "## 定义向量 a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "466d64ec-a195-4519-91d9-672cf451df2e",
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.array([3,4])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ed78e964-2738-408c-868b-40d9ab593e3a",
   "metadata": {},
   "source": [
    "## 自定函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "d6331b8b-2926-4a7c-9f7e-078a14576f8b",
   "metadata": {},
   "outputs": [],
   "source": [
    "def decompose(a, theta):\n",
    "    v1 = np.array([np.cos(theta), np.sin(theta)])\n",
    "    v2 = np.array([-np.sin(theta), np.cos(theta)])\n",
    "\n",
    "    # 标量投影 (坐标)\n",
    "    a_v1 = np.dot(a,v1)\n",
    "    a_v2 = np.dot(a,v2)\n",
    "\n",
    "    # 向量投影 (正交分解)\n",
    "    proj_a_v1 = a_v1 * v1\n",
    "    proj_a_v2 = a_v2 * v2\n",
    "\n",
    "    return proj_a_v1,proj_a_v2"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d15c56f8-c4ce-4683-bf61-ebcd343d45ea",
   "metadata": {},
   "source": [
    "## 正交分解"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "13838426-1429-4dd4-aeb4-6a5de7d0d226",
   "metadata": {},
   "outputs": [],
   "source": [
    "theta = 30\n",
    "theta = theta /180 * np.pi"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "7baf3673-a3ec-492a-9f00-3a974b923bb8",
   "metadata": {},
   "outputs": [],
   "source": [
    "proj_a_v1,proj_a_v2 = decompose(a, theta)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "84498f19-9c83-4780-9e18-e33ce9021893",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([3.98205081, 2.29903811])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "proj_a_v1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "01e36649-1400-48f7-a592-312cd9049a50",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-0.98205081,  1.70096189])"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "proj_a_v2"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0025563c-e03a-4e3b-a337-9f3af1dfc4cf",
   "metadata": {},
   "source": [
    "## 验证"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "25874545-87eb-4a87-8588-79f2ff9a5175",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([3., 4.])"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "proj_a_v1 + proj_a_v2"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6b0a85de-090d-4a55-841d-07b7ebfd4537",
   "metadata": {},
   "source": [
    "作者\t**生姜DrGinger**  \n",
    "脚本\t**生姜DrGinger**  \n",
    "视频\t**崔崔CuiCui**  \n",
    "开源资源\t[**GitHub**](https://github.com/Visualize-ML)  \n",
    "平台\t[**油管**](https://www.youtube.com/@DrGinger_Jiang)\t\t\n",
    "\t\t[**iris小课堂**](https://space.bilibili.com/3546865719052873)\t\t\n",
    "\t\t[**生姜DrGinger**](https://space.bilibili.com/513194466)  "
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python [conda env:base] *",
   "language": "python",
   "name": "conda-base-py"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
